package com.example.meitu.api.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.stream.CollectorUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.meitu.api.common.DateUtils;
import com.example.meitu.api.common.UserContext;
import com.example.meitu.api.common.UserContextUtils;
import com.example.meitu.api.domain.*;
import com.example.meitu.api.dto.*;
import com.example.meitu.api.service.*;
import com.example.meitu.api.dao.ArticleStatisticMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTerm;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* @author 蔡超
* @description 针对表【mt_article_statistic(媒体文章统计表)】的数据库操作Service实现
* @createDate 2024-07-04 10:28:31
*/
@Service
@Slf4j
public class ArticleStatisticServiceImpl extends ServiceImpl<ArticleStatisticMapper, ArticleStatistic>
    implements ArticleStatisticService{

    @Resource
    private ArticleService articleService;

    @Resource
    private MediaTypeService mediaTypeService;

    @Resource
    private UserContextUtils userContextUtils;

    @Resource
    private UserMediaTypeService userMediaTypeService;

    @Resource
    private MediaService mediaService;

    @Resource
    private MediaAccountService mediaAccountService;

    public static final String NEGATIVE_ARTICLE = "negative";

    /**
     * 生成日统计表数据
     */
    @Override
    public void calcBrandMediaStatistic(List<Integer> brandIds, List<Integer> mediaIds,
                                        Integer startTimm, Integer endTimm) {
        for (Integer brandId : brandIds) {
            calcBrandMediaStatistic(brandId, mediaIds, startTimm,endTimm);
        }

    }

    /**
     * 查询概览统计数据
     * 1、查询自选类别
     * 2、根据自选类别查询媒体id
     * 3、根据媒体id查询日统计表，
     * @param brandId
     * @param startTime
     * @param endTime
     * @return
     */
    @Override
    public OverviewDTO overview(Integer userId,Integer brandId, Integer startTime, Integer endTime) {
        Map map = searchMediaIds(userId, brandId);
        Set<Integer> top10MediaIds = (Set<Integer>) map.get("top10MediaIds");
        Set<Integer> totalMdiaIds = (Set<Integer>) map.get("totalMdiaIds");

        List<Integer> competitorBrandIds = UserContextUtils.getCompetitorBrandIds(brandId);
        List<Integer> brandIds = new ArrayList<>();
        brandIds.add(brandId);
        if (CollectionUtil.isNotEmpty(competitorBrandIds)) {
            brandIds.addAll(competitorBrandIds);
        }

        List<ArticleStatistic> articleStatistic = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(brandIds)) {
            //查询日统计表，把数量拼接上
            LambdaQueryWrapper<ArticleStatistic> lambdaQueryWrapper = new LambdaQueryWrapper();
            lambdaQueryWrapper.between(ArticleStatistic::getStatisticTime, startTime, endTime);
            lambdaQueryWrapper.in(ArticleStatistic::getBrandId, brandIds);
            lambdaQueryWrapper.eq(ArticleStatistic::getDelFlag, '0');
            articleStatistic = this.list(lambdaQueryWrapper);
        }

        //品牌表，ID 和 Name 的对应关系
//        Map<Integer,String> brandMap = articleStatistic.stream().collect(Collectors.toMap(
//                    ArticleStatistic::getBrandId,
//                    item -> item.getBrandName() == null ? "":item.getBrandName(),
//                    (oldValue, newValue) -> newValue)
//            );
        Map<Integer,String> brandMap = UserContextUtils.getCompetitorBrand(brandId);

//        List<Integer> collect = articleStatistic.stream().filter(articleStatistic1 -> articleStatistic1.getBrandId().equals(brandId) && top10MediaIds.contains(articleStatistic1.getMediaId()))
//                .map(ArticleStatistic::getMediaId).distinct().collect(Collectors.toList());
//        System.out.println(collect);

        //查询头部媒体id集合
        int topNum = (int)articleStatistic.stream().filter(articleStatistic1 -> articleStatistic1.getBrandId().equals(brandId)
                        && top10MediaIds.contains(articleStatistic1.getMediaId()))
                .map(ArticleStatistic::getMediaId).distinct().count();
        int positiveNum = (int)articleStatistic.stream().filter(articleStatistic1 -> articleStatistic1.getBrandId().equals(brandId)
                        && totalMdiaIds.contains(articleStatistic1.getMediaId())
                        && (articleStatistic1.getPositiveNum() > 0 || articleStatistic1.getNeutralNum() > 0))
                .map(ArticleStatistic::getMediaId).distinct().count();
        int negativeNum = (int)articleStatistic.stream().filter(articleStatistic1 -> articleStatistic1.getBrandId().equals(brandId)
                        && totalMdiaIds.contains(articleStatistic1.getMediaId())
                        && articleStatistic1.getNegativeNum() > 0)
                .map(ArticleStatistic::getMediaId).distinct().count();
        // 整体媒体触达数量（top10+common发表过的文章）
        int totalNum = (int)articleStatistic.stream().filter(articleStatistic1 -> articleStatistic1.getBrandId().equals(brandId)
                        && totalMdiaIds.contains(articleStatistic1.getMediaId()))
                .map(ArticleStatistic::getMediaId).distinct().count();
        List<Integer> num = new ArrayList<>();
        num.add(topNum);
        num.add(positiveNum);
        num.add(negativeNum);
        num.add(totalNum);

        //关注度
        BigDecimal topPercent = top10MediaIds.size() == 0 ? new BigDecimal(0) : new BigDecimal(topNum).divide(new BigDecimal(top10MediaIds.size()),4, RoundingMode.HALF_UP);
        BigDecimal positivePercent = totalNum == 0 ? new BigDecimal(0) : new BigDecimal(positiveNum).divide(new BigDecimal(totalNum),4, RoundingMode.HALF_UP);
        BigDecimal negativePercent = totalNum == 0 ? new BigDecimal(0) : new BigDecimal(negativeNum).divide(new BigDecimal(totalNum),4, RoundingMode.HALF_UP);
        BigDecimal totalPercent = totalMdiaIds.size() == 0 ? new BigDecimal(0) : new BigDecimal(totalNum).divide(new BigDecimal(totalMdiaIds.size()),4, RoundingMode.HALF_UP);
        List<BigDecimal> percent = new ArrayList<>();
        percent.add(topPercent);
        percent.add(positivePercent);
        percent.add(negativePercent);
        percent.add(totalPercent);

        //查询竞品的排序
        List<BrandSortDTO> brandSortList = new ArrayList<>();
        for (Integer competitorBrandId : competitorBrandIds) {
            int topNumCompetitor = (int)articleStatistic.stream().filter(articleStatistic1 -> articleStatistic1.getBrandId().equals(competitorBrandId)
                            && top10MediaIds.contains(articleStatistic1.getMediaId()))
                    .map(ArticleStatistic::getMediaId).distinct().count();
            int positiveNumCompetitor = (int)articleStatistic.stream().filter(articleStatistic1 -> articleStatistic1.getBrandId().equals(competitorBrandId)
                            && totalMdiaIds.contains(articleStatistic1.getMediaId())
                            && (articleStatistic1.getPositiveNum() > 0 || articleStatistic1.getNeutralNum() > 0))
                    .map(ArticleStatistic::getMediaId).distinct().count();
            int negativeNumCompetitor = (int)articleStatistic.stream().filter(articleStatistic1 -> articleStatistic1.getBrandId().equals(competitorBrandId)
                            && totalMdiaIds.contains(articleStatistic1.getMediaId())
                            && articleStatistic1.getNegativeNum() > 0)
                    .map(ArticleStatistic::getMediaId).distinct().count();
            int totalNumCompetitor = (int)articleStatistic.stream().filter(articleStatistic1 -> articleStatistic1.getBrandId().equals(competitorBrandId)
                            && totalMdiaIds.contains(articleStatistic1.getMediaId()))
                    .map(ArticleStatistic::getMediaId).distinct().count();

            BigDecimal topPercentCompetitor = top10MediaIds.size() == 0 ? new BigDecimal(0) : new BigDecimal(topNumCompetitor).divide(new BigDecimal(top10MediaIds.size()),4, RoundingMode.HALF_UP);
            BigDecimal positivePercentCompetitor = totalNumCompetitor == 0 ? new BigDecimal(0) : new BigDecimal(positiveNumCompetitor).divide(new BigDecimal(totalNumCompetitor),4, RoundingMode.HALF_UP);
            BigDecimal negativePercentCompetitor = totalNumCompetitor == 0 ? new BigDecimal(0) : new BigDecimal(negativeNumCompetitor).divide(new BigDecimal(totalNumCompetitor),4, RoundingMode.HALF_UP);
            BigDecimal totalPercentCompetitor = totalMdiaIds.size() == 0 ? new BigDecimal(0):new BigDecimal(totalNumCompetitor).divide(new BigDecimal(totalMdiaIds.size()),4, RoundingMode.HALF_UP);

            BrandSortDTO brandSortDTO = new BrandSortDTO();
            brandSortDTO.setBrandId(competitorBrandId);
            brandSortDTO.setBrandName(brandMap.get(competitorBrandId));
            brandSortDTO.setTopPercent(topPercentCompetitor);
            brandSortDTO.setPositivePercent(positivePercentCompetitor);
            brandSortDTO.setNegativePercent(negativePercentCompetitor);
            brandSortDTO.setTotalPercent(totalPercentCompetitor);
            brandSortList.add(brandSortDTO);
        }

        List<Integer> topPercentList = brandSortList.stream()
                .sorted(Comparator.comparing(BrandSortDTO::getTopPercent).reversed())
                .map(BrandSortDTO::getBrandId).collect(Collectors.toList());
        List<String> topPercentListName = searchBrandName(topPercentList,brandMap);

        List<Integer> positivePercentList = brandSortList.stream()
                .sorted(Comparator.comparing(BrandSortDTO::getPositivePercent).reversed())
                .map(BrandSortDTO::getBrandId).collect(Collectors.toList());
        List<String> positivePercentListName = searchBrandName(positivePercentList,brandMap);

        List<Integer> negativePercentList = brandSortList.stream()
                .sorted(Comparator.comparing(BrandSortDTO::getNegativePercent).reversed())
                .map(BrandSortDTO::getBrandId).collect(Collectors.toList());
        List<String> negativePercentListName = searchBrandName(negativePercentList,brandMap);

        List<Integer> totalPercentList = brandSortList.stream()
                .sorted(Comparator.comparing(BrandSortDTO::getTotalPercent).reversed())
                .map(BrandSortDTO::getBrandId).collect(Collectors.toList());
        List<String> totalPercentListName = searchBrandName(totalPercentList,brandMap);

        //行业内排名
        List<Integer> order = new ArrayList<>();
        order.add(topPercentList.indexOf(brandId)+1);
        order.add(positivePercentList.indexOf(brandId)+1);
        order.add(negativePercentList.indexOf(brandId)+1);
        order.add(totalPercentList.indexOf(brandId)+1);

        //排名详情
        List<List<String>> orderList = new ArrayList<>();
        orderList.add(topPercentListName);
        orderList.add(positivePercentListName);
        orderList.add(negativePercentListName);
        orderList.add(totalPercentListName);

        //结构拼接
        OverviewDTO overviewDTO = new OverviewDTO();
        overviewDTO.setNum(num);
        overviewDTO.setPercent(percent);
        overviewDTO.setOrder(order);
        overviewDTO.setOrderList(orderList);
        return overviewDTO;
    }

    @Override
    public DuibiDTO duibi(OverviewParam overviewParam) {
        Integer brandId = overviewParam.getBrandId();

        List<Integer> competitorBrandIds = UserContextUtils.getCompetitorBrandIds(brandId);
        List<Integer> brandIds = new ArrayList<>();
        brandIds.add(brandId);

        if (CollectionUtil.isNotEmpty(competitorBrandIds)) {
            brandIds.addAll(competitorBrandIds);
        }

        brandIds = CollectionUtil.distinct(brandIds);

        // 用户选择的品牌下的，用户自定义媒体分类，媒体分类下的媒体ID集合
        Map mediaMap = searchMediaIds(overviewParam.getUserId(), brandId);
        Set<Integer> top10MediaIds = (Set<Integer>) mediaMap.get("top10MediaIds");
        Set<Integer> totalMdiaIds = (Set<Integer>) mediaMap.get("totalMdiaIds");

        //查询日统计表，把数量拼接上
        LambdaQueryWrapper<ArticleStatistic> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.between(ArticleStatistic::getStatisticTime, overviewParam.getStartTime(), overviewParam.getEndTime());
        lambdaQueryWrapper.in(ArticleStatistic::getBrandId, brandIds);
        lambdaQueryWrapper.eq(ArticleStatistic::getDelFlag, '0');
        List<ArticleStatistic> articleStatistic = this.list(lambdaQueryWrapper);

        //品牌表，ID 和 Name 的对应关系
//        Map<Integer,String> brandMap = articleStatistic.stream().collect(Collectors.toMap(
//                ArticleStatistic::getBrandId,
//                item -> item.getBrandName() == null ? "":item.getBrandName(),
//                (oldValue, newValue) -> newValue)
//        );

        Map<Integer,String> brandMap = UserContextUtils.getCompetitorBrand(brandId);

        //两层分组，一层品牌，一层媒体
        //头部媒体
        Map<Integer,Map<Integer, List<ArticleStatistic>>> topMap = articleStatistic.stream()
                .filter(articleStatistic1 -> top10MediaIds.contains(articleStatistic1.getMediaId()))
                .collect(Collectors.groupingBy(ArticleStatistic::getBrandId,Collectors.groupingBy(ArticleStatistic::getMediaId)));
        //正向曝光媒体数
        Map<Integer,Map<Integer, List<ArticleStatistic>>> positiveMap = articleStatistic.stream()
                .filter(articleStatistic1 -> (articleStatistic1.getPositiveNum() > 0 || articleStatistic1.getNeutralNum() > 0)
                        && totalMdiaIds.contains(articleStatistic1.getMediaId()))
                .collect(Collectors.groupingBy(ArticleStatistic::getBrandId,Collectors.groupingBy(ArticleStatistic::getMediaId)));
        //负向曝光媒体数
        Map<Integer,Map<Integer, List<ArticleStatistic>>> negativeMap = articleStatistic.stream()
                .filter(articleStatistic1 ->  articleStatistic1.getNegativeNum() > 0
                        && totalMdiaIds.contains(articleStatistic1.getMediaId()))
                .collect(Collectors.groupingBy(ArticleStatistic::getBrandId,Collectors.groupingBy(ArticleStatistic::getMediaId)));
        //整体媒体触达数量
        Map<Integer,Map<Integer, List<ArticleStatistic>>> totalMap = articleStatistic.stream()
                .filter(articleStatistic1 -> totalMdiaIds.contains(articleStatistic1.getMediaId()))
                .collect(Collectors.groupingBy(ArticleStatistic::getBrandId,Collectors.groupingBy(ArticleStatistic::getMediaId)));


        // 最后，只要能计算出出每个品牌的这些字段值，就能进行排序
        List<BrandOverview> brandOverviewList = new ArrayList<>();
        for (Integer i : brandIds) {
            BrandOverview brandOverview = new BrandOverview();
            brandOverview.setBrandId(i);

            //每个品牌的，媒体触达数量
            brandOverview.setTopNum(topMap.get(i) == null ?0:topMap.get(i).size());
            brandOverview.setPositiveNum(positiveMap.get(i) == null ? 0:positiveMap.get(i).size());
            brandOverview.setNegativeNum(negativeMap.get(i) == null ? 0:negativeMap.get(i).size());
//            int totalTopNum = brandOverview.getPositiveNum() + brandOverview.getNegativeNum();
            brandOverview.setTotalTopNum(totalMap.get(i) == null ? 0:totalMap.get(i).size());


            //关注度
            BigDecimal topPercent = new BigDecimal(brandOverview.getTopNum()).divide(new BigDecimal(top10MediaIds.size()),4, RoundingMode.HALF_UP);
            BigDecimal positivePercent = brandOverview.getTotalTopNum() == 0 ? new BigDecimal(0) : new BigDecimal(brandOverview.getPositiveNum()).divide(new BigDecimal(brandOverview.getTotalTopNum()),4, RoundingMode.HALF_UP);
            BigDecimal negativePercent = brandOverview.getTotalTopNum() == 0 ? new BigDecimal(0) : new BigDecimal(brandOverview.getNegativeNum()).divide(new BigDecimal(brandOverview.getTotalTopNum()),4, RoundingMode.HALF_UP);
            BigDecimal totalPercent = new BigDecimal(brandOverview.getTotalTopNum()).divide(new BigDecimal(totalMdiaIds.size()),4, RoundingMode.HALF_UP);

            brandOverview.setTopPercent(topPercent);
            brandOverview.setPositivePercent(positivePercent);
            brandOverview.setNegativePercent(negativePercent);
            brandOverview.setTotalPercent(totalPercent);

            brandOverviewList.add(brandOverview);
        }

        //根据关注度排序
        List<BigDecimal> topSort = brandOverviewList.stream()
                .sorted(Comparator.comparing(BrandOverview::getTopPercent).reversed())
                .map(BrandOverview::getTopPercent).collect(Collectors.toList());

        List<BigDecimal> positiveSort = brandOverviewList.stream()
                .sorted(Comparator.comparing(BrandOverview::getPositivePercent).reversed())
                .map(BrandOverview::getPositivePercent).collect(Collectors.toList());

        List<BigDecimal> negativeSort = brandOverviewList.stream()
                .sorted(Comparator.comparing(BrandOverview::getNegativePercent).reversed())
                .map(BrandOverview::getNegativePercent).collect(Collectors.toList());

        List<BigDecimal> totalSort = brandOverviewList.stream()
                .sorted(Comparator.comparing(BrandOverview::getTotalPercent).reversed())
                .map(BrandOverview::getTotalPercent).collect(Collectors.toList());

        for (BrandOverview brandOverview : brandOverviewList) {
            brandOverview.setTopSort(topSort.indexOf(brandOverview.getTopPercent()) + 1);
            brandOverview.setPositiveSort(positiveSort.indexOf(brandOverview.getPositivePercent()) + 1);
            brandOverview.setNegativeSort(negativeSort.indexOf(brandOverview.getNegativePercent()) + 1);
            brandOverview.setTotalSort(totalSort.indexOf(brandOverview.getTotalPercent()) + 1);
        }

        // 计算出每个品牌的12个字段，放到map里面
        Map<Integer,BrandOverview> resultMap = brandOverviewList.stream().collect(Collectors.toMap(BrandOverview::getBrandId,a->a,((k1,k2) -> k1)));

        //拼接数据
        DuibiDTO duibiDTO = new DuibiDTO();

        List<Integer> topNum = new ArrayList<>();
        List<Integer> positiveNum = new ArrayList<>();
        List<Integer> negativeNum = new ArrayList<>();
        List<Integer> totalNum = new ArrayList<>();

        List<BigDecimal> topPercent = new ArrayList<>();
        List<BigDecimal> positivePercent = new ArrayList<>();
        List<BigDecimal> negativePercent = new ArrayList<>();
        List<BigDecimal> totalPercent = new ArrayList<>();

        List<Integer> topSortResult = new ArrayList<>();
        List<Integer> positiveSortResult = new ArrayList<>();
        List<Integer> negativeSortResult = new ArrayList<>();
        List<Integer> totalSortResult = new ArrayList<>();

        List<BrandSort> topListName = new ArrayList<>();
        List<BrandSort> positiveListName = new ArrayList<>();
        List<BrandSort> negativeListName = new ArrayList<>();
        List<BrandSort> totalListName = new ArrayList<>();

        //要返回的品牌数据，前面计算的 brandIds 是本品 + 竞品的全部数据
        List<Integer> resultbrandIds = new ArrayList<>();
        resultbrandIds.add(overviewParam.getBrandId());
        resultbrandIds.addAll(overviewParam.getCompareBrandIds());

        for (Integer id : resultbrandIds) {
            BrandOverview brandOverview = resultMap.get(id);

            topNum.add(brandOverview.getTopNum());
            positiveNum.add(brandOverview.getPositiveNum());
            negativeNum.add(brandOverview.getNegativeNum());
            totalNum.add(brandOverview.getTotalTopNum());

            topPercent.add(brandOverview.getTopPercent());
            positivePercent.add(brandOverview.getPositivePercent());
            negativePercent.add(brandOverview.getNegativePercent());
            totalPercent.add(brandOverview.getTotalPercent());

            topSortResult.add(brandOverview.getTopSort());
            positiveSortResult.add(brandOverview.getPositiveSort());
            negativeSortResult.add(brandOverview.getNegativeSort());
            totalSortResult.add(brandOverview.getTotalSort());

            //拼接显示的格式 "海尔集团No.1"
            topListName.add(new BrandSort(id,
                    String.format("%sNo.%s",brandMap.get(id)== null?String.valueOf(id):brandMap.get(id),brandOverview.getTopSort()),
                    brandOverview.getTopSort()));
            positiveListName.add(new BrandSort(id,
                    String.format("%sNo.%s",brandMap.get(id)== null?String.valueOf(id):brandMap.get(id),brandOverview.getPositiveSort()),
                    brandOverview.getPositiveSort()));
            negativeListName.add(new BrandSort(id,
                    String.format("%sNo.%s",brandMap.get(id)== null?String.valueOf(id):brandMap.get(id),brandOverview.getNegativeSort()),
                    brandOverview.getNegativeSort()));
            totalListName.add(new BrandSort(id,
                    String.format("%sNo.%s",brandMap.get(id)== null?String.valueOf(id):brandMap.get(id),brandOverview.getTotalSort()),
                    brandOverview.getTotalSort()));

        }
        List<List<Integer>> num = new ArrayList<>();
        num.add(topNum);
        num.add(positiveNum);
        num.add(negativeNum);
        num.add(totalNum);
        duibiDTO.setNum(num);

        List<List<BigDecimal>> percent = new ArrayList<>();
        percent.add(topPercent);
        percent.add(positivePercent);
        percent.add(negativePercent);
        percent.add(totalPercent);
        duibiDTO.setPercent(percent);

        List<List<Integer>> order = new ArrayList<>();
        order.add(topSortResult);
        order.add(positiveSortResult);
        order.add(negativeSortResult);
        order.add(totalSortResult);
        duibiDTO.setOrder(order);

        List<List<String>> orderList = new ArrayList<>();
        List<String> topCollect = topListName.stream().map(BrandSort::getName).collect(Collectors.toList());
        List<String> positiveCollect = positiveListName.stream().map(BrandSort::getName).collect(Collectors.toList());
        List<String> negativeCollect = negativeListName.stream().map(BrandSort::getName).collect(Collectors.toList());
        List<String> totalCollect = totalListName.stream().map(BrandSort::getName).collect(Collectors.toList());
        orderList.add(topCollect);
        orderList.add(positiveCollect);
        orderList.add(negativeCollect);
        orderList.add(totalCollect);
        duibiDTO.setOrderList(orderList);

        return duibiDTO;
    }

    private List<String> searchBrandName(List<Integer> totalPercentList, Map<Integer, String> brandMap) {
        if (CollectionUtil.isEmpty(totalPercentList)) {
            return new ArrayList<>();
        }
        List<String> list = new ArrayList<>();
        for (Integer integer : totalPercentList) {
            list.add(brandMap.get(integer)== null?String.valueOf(integer):brandMap.get(integer));
        }
        return list;
    }

    /**
     * 以分类的维度，展示每个分类的数据，对应覆盖图里面的最小的分类卡片
     * @param fugaituParam
     * @return
     */
    @Override
    public List<FugaituCardDTO> fugaitu(FugaituParam fugaituParam) {

        //判断是时间对比还是品牌对比, 时间对比优先
        int type = 1; //1无对比；2时间对比；3品牌对比
        String[] compareBrandIds = new String[]{};

        Integer compareStartTime = fugaituParam.getCompareStartTime();
        Integer compareEndTimeTime = fugaituParam.getCompareEndTimeTime();
        if (compareStartTime != null || compareEndTimeTime != null) {
            type =2;
        } else if (StringUtils.isNotEmpty(fugaituParam.getCompareBrandId())) {
            compareBrandIds = fugaituParam.getCompareBrandId().split(",");
            type = 3;
        }

        Map map = searchMediaIds(fugaituParam.getUserId(), fugaituParam.getBrandId());
        List<FugaituCardDTO> fugaituCardDTOList = (List<FugaituCardDTO>) map.get("fugaituCardDTOList");

        String articleType = fugaituParam.getType();

        //只查询一次媒体表，把所有的媒体都查询出来，再往 fugaituCardDTO 上拼接，不要在for循环里面拼接
        LambdaQueryWrapper<Media> mediaLambdaQueryWrapper = new LambdaQueryWrapper<>();
        mediaLambdaQueryWrapper.eq(Media::getDelFlag, '0');
        List<Media> mediaList = mediaService.list(mediaLambdaQueryWrapper);
        Map<Integer,Media> mediaMap = mediaList.stream().collect(Collectors.toMap(Media::getId, a->a,(k1,k2)->k1));

        //查询日统计表, 根据mediaId分组，生成positiveMap  neutralMap negativeMap
        LambdaQueryWrapper<ArticleStatistic> articleStatisticLambdaQueryWrapper = new LambdaQueryWrapper<>();
        articleStatisticLambdaQueryWrapper.eq(ArticleStatistic::getBrandId, fugaituParam.getBrandId());
        articleStatisticLambdaQueryWrapper.eq(ArticleStatistic::getDelFlag,'0');
        articleStatisticLambdaQueryWrapper.between(ArticleStatistic::getStatisticTime,fugaituParam.getStartTime(),fugaituParam.getEndTime());
        if (StringUtils.isNotEmpty(articleType) && articleType.equals(NEGATIVE_ARTICLE)) {
            articleStatisticLambdaQueryWrapper.ge(ArticleStatistic::getNegativeNum, 1);
        }
        List<ArticleStatistic> articleStatistics = list(articleStatisticLambdaQueryWrapper);
//        Map<Integer, Integer> positiveMap = articleStatistics.stream().collect(Collectors.groupingBy(ArticleStatistic::getMediaId, Collectors.summingInt(ArticleStatistic::getPositiveNum)));
//        Map<Integer, Integer> neutralMap = articleStatistics.stream().collect(Collectors.groupingBy(ArticleStatistic::getMediaId, Collectors.summingInt(ArticleStatistic::getNeutralNum)));
//        Map<Integer, Integer> negativeMap = articleStatistics.stream().collect(Collectors.groupingBy(ArticleStatistic::getMediaId, Collectors.summingInt(ArticleStatistic::getNegativeNum)));
        Map<Integer, Integer> totalMap = articleStatistics.stream().collect(Collectors.groupingBy(ArticleStatistic::getMediaId, Collectors.summingInt(ArticleStatistic::getTotalNum)));

        //时间对比
        Map<Integer, Integer> positiveMap2 = new HashMap<>();
        Map<Integer, Integer> neutralMap2 = new HashMap<>();
        Map<Integer, Integer> negativeMap2 = new HashMap<>();
        Map<Integer, Integer> totalMap2 = new HashMap<>();
        if (type == 2) {
            LambdaQueryWrapper<ArticleStatistic> articleStatisticLambdaQueryWrapper2 = new LambdaQueryWrapper<>();
            articleStatisticLambdaQueryWrapper2.eq(ArticleStatistic::getBrandId, fugaituParam.getBrandId());
            articleStatisticLambdaQueryWrapper2.eq(ArticleStatistic::getDelFlag,'0');
            articleStatisticLambdaQueryWrapper2.between(ArticleStatistic::getStatisticTime,compareStartTime,compareEndTimeTime);
            if (StringUtils.isNotEmpty(articleType) && articleType.equals(NEGATIVE_ARTICLE)) {
                articleStatisticLambdaQueryWrapper2.ge(ArticleStatistic::getNegativeNum, 1);
            }
            List<ArticleStatistic> articleStatistics2 = list(articleStatisticLambdaQueryWrapper2);
//            positiveMap2 = articleStatistics2.stream().collect(Collectors.groupingBy(ArticleStatistic::getMediaId, Collectors.summingInt(ArticleStatistic::getPositiveNum)));
//            neutralMap2 = articleStatistics2.stream().collect(Collectors.groupingBy(ArticleStatistic::getMediaId, Collectors.summingInt(ArticleStatistic::getNeutralNum)));
//            negativeMap2 = articleStatistics2.stream().collect(Collectors.groupingBy(ArticleStatistic::getMediaId, Collectors.summingInt(ArticleStatistic::getNegativeNum)));
            totalMap2 = articleStatistics2.stream().collect(Collectors.groupingBy(ArticleStatistic::getMediaId, Collectors.summingInt(ArticleStatistic::getTotalNum)));
            if (CollectionUtil.isEmpty(totalMap2)){
                totalMap2.put(0,0);
            }
        }

        //品牌对比
        List<Map<Integer, Integer>> compareList = new ArrayList<>();
        if (type == 3) {
            for (String brandId : compareBrandIds) {
                LambdaQueryWrapper<ArticleStatistic> articleStatisticLambdaQueryWrapper3 = new LambdaQueryWrapper<>();
                articleStatisticLambdaQueryWrapper3.eq(ArticleStatistic::getBrandId, brandId);
                articleStatisticLambdaQueryWrapper3.eq(ArticleStatistic::getDelFlag,'0');
                articleStatisticLambdaQueryWrapper3.between(ArticleStatistic::getStatisticTime,fugaituParam.getStartTime(),fugaituParam.getEndTime());
                List<ArticleStatistic> articleStatistics2 = list(articleStatisticLambdaQueryWrapper3);
//                Map<Integer, Integer> positiveMap3 = articleStatistics2.stream().collect(Collectors.groupingBy(ArticleStatistic::getMediaId, Collectors.summingInt(ArticleStatistic::getPositiveNum)));
//                Map<Integer, Integer> neutralMap3 = articleStatistics2.stream().collect(Collectors.groupingBy(ArticleStatistic::getMediaId, Collectors.summingInt(ArticleStatistic::getNeutralNum)));
//                Map<Integer, Integer> negativeMap3 = articleStatistics2.stream().collect(Collectors.groupingBy(ArticleStatistic::getMediaId, Collectors.summingInt(ArticleStatistic::getNegativeNum)));
                Map<Integer, Integer> totalMap3 = articleStatistics2.stream().collect(Collectors.groupingBy(ArticleStatistic::getMediaId, Collectors.summingInt(ArticleStatistic::getTotalNum)));
                compareList.add(totalMap3);
            }
        }

        //查询本品+所有竞品的统计数据，根据medisId分组，生成MediaStatistic对象
        List<Integer> competitorBrandIds = UserContextUtils.getCompetitorBrandIds(fugaituParam.getBrandId());
        LambdaQueryWrapper<ArticleStatistic> competitorBrandIdsWrapper = new LambdaQueryWrapper<>();
        competitorBrandIdsWrapper.in(ArticleStatistic::getBrandId, competitorBrandIds);
        competitorBrandIdsWrapper.eq(ArticleStatistic::getDelFlag,'0');
        competitorBrandIdsWrapper.between(ArticleStatistic::getStatisticTime,fugaituParam.getStartTime(),fugaituParam.getEndTime());
        List<ArticleStatistic> mediaStatistics = list(competitorBrandIdsWrapper);
        //mediaStatistics转成Map<Integer,Long>根据mediaId分组，统计totalNum
        Map<Integer, Integer> competitorTotalMap = mediaStatistics.stream().collect(Collectors.groupingBy(ArticleStatistic::getMediaId, Collectors.summingInt(ArticleStatistic::getTotalNum)));

        List<AccountPlatformDTO> list = mediaAccountService.getAllAccountPlatforms();
        Map<String,String> accountMap = list.stream().collect(Collectors.toMap(AccountPlatformDTO::getAccountName, AccountPlatformDTO::getPlatform));

        for (FugaituCardDTO fugaituCardDTO : fugaituCardDTOList) {
            List<FugaituCardMediaDTO> medisList = new ArrayList<>();
            List<Integer> top10MediaId = fugaituCardDTO.getTop10MediaId();
            if (CollectionUtil.isEmpty(top10MediaId)) {
                continue;
            }
//            log.info("fugaitu mediaId: " + fugaituCardDTO.getName());
//            if ("自媒体-市场营销".equals(fugaituCardDTO.getName()) && "6".equals(fugaituCardDTO.getScope())) {
//                log.info("fugaitu mediaId: " + fugaituCardDTO.getName());
//            }
            try {
                for (Integer mediaId : top10MediaId) {
                    Media media = mediaMap.get(mediaId);
                    if (media == null) {
                        log.error("mediaId not found: " + mediaId);
                        continue;
                    }
                    FugaituCardMediaDTO fugaituCardMediaDTO = new FugaituCardMediaDTO();
                    fugaituCardMediaDTO.setSubMediaId(media.getSubUnionMediaId());
                    // 用媒体名称查询是否有同名媒体账号，返回账号对应的媒体平台
                    fugaituCardMediaDTO.setPlatform(accountMap.get(media.getMediaName()));
                    fugaituCardMediaDTO.setMediaId(media.getId());
                    fugaituCardMediaDTO.setMediaName(media.getMediaName());
//                int[] publishNum = new int[]{totalMap.get(mediaId)!=null?totalMap.get(mediaId):0};
                    int[] publishNum = buildPublishNum(mediaId, type, totalMap, totalMap2, compareList);


                    fugaituCardMediaDTO.setPublishNum(publishNum);
//                int[] publishFlag = new int[]{totalMap.get(mediaId)!=null?1:0};
                    int[] publishFlag = buildPublishFlag(mediaId, type, totalMap, totalMap2, compareList);
                    fugaituCardMediaDTO.setPublishFlag(publishFlag);

                    // 用于覆盖图中，同一媒体类别下的媒体排序
//                int firstPublishNum = totalMap.get(mediaId)!=null?totalMap.get(mediaId):0;
                    // 数组中的元素(本品 + 所有竞品的发布文章数)进行求和
                    int firstPublishNum = competitorTotalMap.get(mediaId) == null ? 0 : competitorTotalMap.get(mediaId);
                    fugaituCardMediaDTO.setFirstPublishNum(firstPublishNum);
                    medisList.add(fugaituCardMediaDTO);
                }
                medisList = medisList.stream().sorted(Comparator.comparing(FugaituCardMediaDTO::getFirstPublishNum).reversed()).collect(Collectors.toList());
                fugaituCardDTO.setList(medisList);
                // 清空不用的参数
                fugaituCardDTO.setCommonMediaId(new ArrayList<>());
                fugaituCardDTO.setTop10MediaId(new ArrayList<>());
            } catch (Exception e) {
                log.error("fugaitu mediaId: " + fugaituCardDTO.getName());
                log.error(e.getMessage(), e);
            }

        }
        return fugaituCardDTOList;
    }



    private int[] buildPublishNum(Integer mediaId, int type, Map<Integer, Integer> totalMap, Map<Integer, Integer> totalMap2, List<Map<Integer, Integer>> compareList) {
        List<Integer> list = new ArrayList<>();
        list.add(totalMap.get(mediaId) !=null ? totalMap.get(mediaId):0);
        if (type == 2) {
            list.add(totalMap2.get(mediaId) !=null ? totalMap2.get(mediaId) : 0);
        } else if (type == 3){
            for (Map<Integer, Integer> integerIntegerMap : compareList) {
                list.add(integerIntegerMap.get(mediaId) != null ? integerIntegerMap.get(mediaId) : 0);
            }
        }
        return list.stream().mapToInt(Integer::valueOf).toArray();
    }

    /**
     * 标识媒体发布状态
     * @param mediaId
     * @param type
     * @param totalMap
     * @param totalMap2
     * @param compareList
     * @return
     */
    private int[] buildPublishFlag(Integer mediaId, int type, Map<Integer, Integer> totalMap, Map<Integer, Integer> totalMap2, List<Map<Integer, Integer>> compareList) {
        List<Integer> list = new ArrayList<>();
        list.add(totalMap.get(mediaId) != null ? 1 : 0);
        if (type == 2) {
            list.add(totalMap2.get(mediaId) !=null ? 1 : 0);
        } else if (type == 3){
            for (Map<Integer, Integer> integerIntegerMap : compareList) {
                list.add(integerIntegerMap.get(mediaId) != null ? 1 : 0);
            }
        }
        return list.stream().mapToInt(Integer::valueOf).toArray();
    }

    /**
     * 根据查询参数，获取媒体id列表
     * @return
     */
    private Map<String,Object> searchMediaIds(Integer userId, Integer brandId){
        //用户选中的媒体分类
        List<Integer> checkList = new ArrayList<>();
        //查询自选分类
        LambdaQueryWrapper<UserMediaType> userMediaTypeWrapper = new LambdaQueryWrapper<>();
        userMediaTypeWrapper.eq(UserMediaType::getUserId, userId);
        userMediaTypeWrapper.eq(UserMediaType::getBrandId, brandId);
        userMediaTypeWrapper.eq(UserMediaType::getDelFlag, '0');
        userMediaTypeWrapper.orderByDesc(UserMediaType::getCreateTime);
        List<UserMediaType> list = userMediaTypeService.list(userMediaTypeWrapper);
        if (CollectionUtil.isEmpty(list)) {
            // 如果没有自定义媒体类别，查询user_id brand_id 为0的默认值
            LambdaQueryWrapper<UserMediaType> userMediaTypeWrapperDefault = new LambdaQueryWrapper<>();
            userMediaTypeWrapperDefault.eq(UserMediaType::getUserId, 0);
            userMediaTypeWrapperDefault.eq(UserMediaType::getBrandId, 0);
            list = userMediaTypeService.list(userMediaTypeWrapperDefault);
        }
        if (CollectionUtil.isNotEmpty(list)) {
            UserMediaType userMediaType = list.get(0);
            String topStr = userMediaType.getTopMediaTypeId();
            String subStr = userMediaType.getSubdivideMediaTypeId();
            if (StringUtils.isNotBlank(topStr)) {
                List<Integer> topCheckList = Arrays.asList(topStr.split(","))
                        .stream().filter(v -> StringUtils.isNotBlank(v))
                        .map(Integer::parseInt).collect(Collectors.toList());
                checkList.addAll(topCheckList);
            }
            if (StringUtils.isNotBlank(subStr)){
                List<Integer> subdivideCheckList = Arrays.asList(subStr.split(","))
                        .stream().filter(v -> StringUtils.isNotBlank(v))
                        .map(Integer::parseInt).collect(Collectors.toList());
                checkList.addAll(subdivideCheckList);
            }
        }

        //根据分类id查询分类列表
        LambdaQueryWrapper<MediaType> lambdaQueryWrapper = new LambdaQueryWrapper();
        List<String> scope = new ArrayList<>(Arrays.asList("1", "2", "3","4", "5", "6"));
        lambdaQueryWrapper.in(MediaType::getScope, scope);
        lambdaQueryWrapper.eq(MediaType::getDelFlag, '0');
        if (CollectionUtil.isNotEmpty(checkList)) {
            // 用户没有自定义的媒体分类，默认查询全部
            lambdaQueryWrapper.in(MediaType::getId, checkList);
        }
        lambdaQueryWrapper.orderByAsc(MediaType::getSort);
        List<MediaType> mediaTypeList = mediaTypeService.list(lambdaQueryWrapper);

        Map<Integer, MediaType> allMediaType = mediaTypeService.list().stream().collect(Collectors.toMap(MediaType::getId, mediaType -> mediaType));

        //全部的媒体id
        Integer mediaIds = mediaService.size();


        Set<Integer> top10MediaIds = new HashSet<>();
        Set<Integer> commonMdiaIds = new HashSet<>();
        List<FugaituCardDTO> fugaituCardDTOList = new ArrayList<>();
        for (MediaType mediaType : mediaTypeList) {
            FugaituCardDTO fugaituCardDTO = new FugaituCardDTO();
            fugaituCardDTO.setName(mediaType.getName());
            fugaituCardDTO.setPName(allMediaType.get(mediaType.getPid()) == null ? "" : allMediaType.get(mediaType.getPid()).getName());
            fugaituCardDTO.setScope(mediaType.getScope());

            String top10 = mediaType.getTop10Mdiaids();
            if (StringUtils.isNotEmpty(top10)) {
                List<Integer> top10MediaId = Arrays.asList(top10.split(","))
                        .stream().filter(v -> StringUtils.isNotBlank(v))
                        .map(Integer::parseInt).collect(Collectors.toList());
                fugaituCardDTO.setTop10MediaId(top10MediaId);
                top10MediaIds.addAll(top10MediaId);
            }

            String commonMdiaids = mediaType.getCommonMdiaids();
            if (StringUtils.isNotEmpty(commonMdiaids)) {
                List<Integer> commonMdiaId = Arrays.asList(commonMdiaids.split(","))
                        .stream().filter(v -> StringUtils.isNotBlank(v))
                        .map(Integer::parseInt).collect(Collectors.toList());
                fugaituCardDTO.setCommonMediaId(commonMdiaId);
                commonMdiaIds.addAll(commonMdiaId);
            }
            fugaituCardDTO.setList(new ArrayList<>());
            fugaituCardDTOList.add(fugaituCardDTO);
        }
        Set<Integer> totalMdiaIds = new HashSet<>();
        totalMdiaIds.addAll(top10MediaIds);
        totalMdiaIds.addAll(commonMdiaIds);
        log.info("品牌id:{},top10MediaIds:{}",brandId,top10MediaIds);
        Map map = new HashMap();
        map.put("fugaituCardDTOList", fugaituCardDTOList);
//        map.put("mediaIds", mediaIds);
        map.put("top10MediaIds", top10MediaIds);
        map.put("commonMdiaIds", commonMdiaIds);
        map.put("totalMdiaIds", totalMdiaIds);
        return map;
    }


    /**
     * 生成一个品牌的统计数据
     * @param brandId
     * @param mediaIds
     * @param startTimm
     * @param endTimm
     */
    @Async
    public void calcBrandMediaStatistic(Integer brandId,List<Integer> mediaIds,
                                         Integer startTimm, Integer endTimm){
        log.info("calcBrandMediaStatistic, brandId:{},mediaIds:{}, startTimm:{}, endTimm:{}"
                ,brandId, mediaIds.toArray(),startTimm,endTimm);
        List<ArticleStatistic> result = new ArrayList<>();

        LambdaQueryWrapper<Article> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.eq(Article::getBrandId, brandId);
        lambdaQueryWrapper.eq(Article::getDelFlag, '0');
        lambdaQueryWrapper.between(Article::getPublishTime,startTimm,endTimm);
        if (CollectionUtil.isNotEmpty(mediaIds)) {
            lambdaQueryWrapper.in(Article::getMediaId, mediaIds);
        }
        List<Article> articleList = articleService.list(lambdaQueryWrapper);
        //一个品牌的所有文章，根据媒体进行区分
        Map<Integer,List<Article>> mediaMap = articleList.stream().collect(Collectors.groupingBy(Article::getMediaId));
        for (Integer mediaId : mediaMap.keySet()) {
            //循环所有的媒体，每个媒体，再根据日期进行统计
            Map<LocalDate,List<Article>> dateMediaMap = mediaMap.get(mediaId).stream().collect(Collectors.groupingBy(Article::getPublishDate));
            for (LocalDate localDate : dateMediaMap.keySet()) {
//                if (mediaId == 40 && DateUtils.localdateConvertTime(localDate) == 1734278400){
//                    log.info("size:" + dateMediaMap.get(localDate).size());
//                }
                List<Article> list = dateMediaMap.get(localDate);
                Article firstArticle = list.get(0);
                ArticleStatistic articleStatistic = new ArticleStatistic();
                articleStatistic.setMediaId(mediaId);
                articleStatistic.setStatisticTime(DateUtils.localdateConvertTime(localDate));

                articleStatistic.setBrandId(firstArticle.getBrandId());
                articleStatistic.setBrandName(firstArticle.getBrandName());

                //统计三个数量和总数(0负面；1正面；2中性)
                long negativeNum = list.stream().filter(article -> article.getPositiveFlag().equals(0)).count();
                long positiveNum = list.stream().filter(article -> article.getPositiveFlag().equals(1)).count();
                long neutralNum = list.stream().filter(article -> article.getPositiveFlag().equals(2)).count();
                long total = positiveNum + neutralNum + negativeNum;
                articleStatistic.setPositiveNum((int)positiveNum);
                articleStatistic.setNeutralNum((int)neutralNum);
                articleStatistic.setNegativeNum((int)negativeNum);
                articleStatistic.setTotalNum((int)total);

                articleStatistic.setCreateTime(new Date());
                result.add(articleStatistic);
            }
        }
        saveBatch(result);
        log.info("calcBrandMediaStatistic end, brandId:{},mediaIds:{}, startTimm:{}, endTimm:{}"
                ,brandId, mediaIds.toArray(),startTimm,endTimm);
    }

}